package game.screens;

import game.AmministratoreBuilder;
import game.Amministratore;
import game.Attore;
import game.GeneratoreAttori;

import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;


import asciiPanel.AsciiPanel;

/*	Schermata di gioco
 * 	gestisce l'ambiente di gioco nel caso di vincita viene creato uno WinScreen
 *  in caso di perdita viene creato uno LoseScreen
 *  gestisce anche gli eventi di Save game e di Load Game
 * */
public class PlayScreen implements Screen {
	private Amministratore amministratore;
	private Attore player;
	private int screenWidth;
	private int screenHeight;
	
	private GeneratoreAttori stuffFactory;
	private int tempo;
	/*Nuova gioco*/
	public PlayScreen(){
		screenWidth = 80;
		screenHeight = 23;
		tempo=0;
	
		createWorld();
		
		stuffFactory = new GeneratoreAttori(amministratore);
		createCreatures(stuffFactory);
	}
	/*Carica un salvataggio 
	 * @param file : un file di testo con gli elementi del gioco
	*/
	public PlayScreen(File file){
		screenWidth = 80;
		screenHeight = 23;
		tempo=0;
		createCreatures(stuffFactory);
		createWorld();
		
		stuffFactory = new GeneratoreAttori(amministratore);
		
		load(file);
	}
	
	

	/*Crea gli attori compreso il giocatore
	 * @param generatore aggiunge gli attori al Amministratore
	 * */
	private void createCreatures(GeneratoreAttori generatore){
		player = generatore.newPlayer();
		
		for (int i = 0; i < 30; i++){
			generatore.newOrco();
		}
		
	}
	/*
	 * Crea la prigione i muri,l'entrata, l'uscita e le pozioni 
	 * 
	 */
	private void createWorld(){
		amministratore = new AmministratoreBuilder(80, 23)
					.stanza()
					.build();
	}
	
	/*
	 * Mostra output nel AsciiPanel
	 * @param terminal Il pannello AsciPanel
	 */
	@Override
	public void displayOutput(AsciiPanel terminal) {
		
		
		displayTiles(terminal);
		
		terminal.writeCenter("-- Rouge Game --", 23);

		String stats = String.format(" %3d/%3d hp", player.hp(), player.maxHp());
		terminal.write(stats, 1, 23);
	}

	/*
	 * Mostra pozioni,muri,entrata e uscita
	 */
	private void displayTiles(AsciiPanel terminal) {
		for (int x = 0; x < screenWidth; x++){
			for (int y = 0; y < screenHeight; y++){
				int wx = x ;
				int wy = y ;

				Attore attore = amministratore.attore(wx, wy);
				if (attore != null)
					terminal.write(attore.glyph(), attore.x , attore.y , attore.color());
				else
					terminal.write(amministratore.glyph(wx, wy), x, y, amministratore.color(wx, wy));
			}
		}
	}
	
	/*
	 *Risponde agli input da tastiera 
	 * @param key il carattere battuto
	 */
	@Override
	public Screen respondToUserInput(KeyEvent key) {
		tempo++;
		if((tempo%3)==0)
			player.incAttack();
		if((tempo==15)||(tempo==30))
			stuffFactory.newBoss();
		
		switch (key.getKeyCode()){
		case KeyEvent.VK_LEFT:
		case KeyEvent.VK_J: if(player.moveByPlayer(-1, 0))
								return new WinScreen(); 
								break;
		case KeyEvent.VK_RIGHT:
		case KeyEvent.VK_L: if(player.moveByPlayer(1, 0))
			return new WinScreen(); 
			break;
		case KeyEvent.VK_UP:
		case KeyEvent.VK_I: if(player.moveByPlayer(0, -1))
			return new WinScreen(); 
			break;
		case KeyEvent.VK_DOWN:
		case KeyEvent.VK_COMMA: if(player.moveByPlayer(0, 1))
			return new WinScreen(); 
			break;
		case KeyEvent.VK_U: if(player.moveByPlayer(-1, -1))
			return new WinScreen(); 
			break;
		case KeyEvent.VK_O: if(player.moveByPlayer(1, -1))
			return new WinScreen(); 
			break;
		case KeyEvent.VK_M: if(player.moveByPlayer(-1, 1))
			return new WinScreen(); 
			break;
		case KeyEvent.VK_PERIOD: if(player.moveByPlayer(1, 1))
			return new WinScreen(); 
			break;
		case KeyEvent.VK_K: if(player.moveByPlayer(0, 0))
			return new WinScreen(); 
			break;
		}
		
		amministratore.update();
		if (player.hp() < 1)
			return new LoseScreen();
		return this;
	}


	/*
	 * Salva il gioco in un file di testo
	 * @file il file destinazione
	 */
	@Override
	public Screen save(File file) {
		if(!file.exists())
		{
			try {
				file.createNewFile();
			} catch (IOException e) {
								e.printStackTrace();
			}
		}
		FileWriter fw = null;
		BufferedWriter bw = null;
		try {
			fw = new FileWriter(file.getAbsoluteFile());
			bw = new BufferedWriter(fw);
			bw.write(amministratore.Save());
			
			
		} catch (IOException e) {
			
			e.printStackTrace();
		}finally{
			try {
				bw.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		System.out.print(amministratore.Save());
		return this;
	}


	/*
	 * Carica una partita: elimina tutti gli attori e le pozioni dalla prigione e aggiorna attraverso il file di testo
	 * Miglioramenti:controllare che il file di testo sia in un formato valido
	 * @param file il file contenente un salvataggio 
	 */
	@Override
	public Screen load(File file) {
		
		amministratore.removeAll();
		BufferedReader br = null;
				
				try{
					String line;
					br = new BufferedReader(new FileReader(file.getAbsoluteFile()));
					while((line=br.readLine())!=null)
					{
						String[] tok=line.split("[,]");
						
						if(tok[0].equals("pozione")){
							amministratore.addItem(Integer.parseInt(tok[1]),Integer.parseInt(tok[2]));
						}
						
						if(tok[0].equals("player"))
						{
							player=stuffFactory.newPlayer(tok);
							
						}
						if(tok[0].equals("orco"))
						{
							stuffFactory.newOrco(tok);
						}
						if(tok[0].equals("The Boss"))
						{
							stuffFactory.newBoss(tok);
						}
					}
				}
				catch(IOException e){
					e.printStackTrace();
				}finally{
					try{
						if(br != null)
							br.close();
					}catch(IOException ex)
					{
						ex.printStackTrace();
					}
				}
				
				return this;
	}
}
